package com.rtsapp.server.gamelog.client.tail;

import com.rtsapp.server.gamelog.cmd.cmd.StartLogCollectResponse;
import com.rtsapp.server.gamelog.cmd.model.LogProgress;
import com.rtsapp.server.gamelog.cmd.model.ServerInfo;
import com.rtsapp.server.gamelog.cmd.model.ServerLogProgress;
import com.rtsapp.server.logger.Logger;
import com.rtsapp.server.logger.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 管理所有日志采集的类
 */
public class LogTailMgr {

    private static final Logger LOG = LoggerFactory.getLogger(LogTailMgr.class);

    //默认10毫秒循环一次
    private static final long DEFAULT_A_LOOP_MILS = 1000;
    //日志大小
    private static final int DEFAULT_TAIL_LINE_SIZE = 100;


    private final ILogProcessor tailProcessor;
    //所有的日志dir
    private final List<LogDir> logDirs;
    //所有的日志组件
    private final List<LogTail> logTailList = new ArrayList<>();

    private volatile CountDownLatch countDownLatch;
    private volatile boolean stopCollect = true;


    public LogTailMgr(ILogProcessor tailProcessor, List<LogDir> logDirs) {
        this.tailProcessor = tailProcessor;
        this.logDirs = logDirs;
    }

    /**
     * 启动日志收集
     *
     * @param response
     */
    public void startLogCollect(StartLogCollectResponse response) {

        synchronized (this) {

            //已经启动啦
            if (countDownLatch != null && countDownLatch.getCount() > 0) {
                return;
            }

            //创建所有的日志Tail
            logTailList.clear();

            ArrayList<ServerLogProgress> progressesList = response.getLogProgressList();
            for (ServerLogProgress progress : progressesList) {

                LogDir dir = getLogDir(progress.getServerInfo());
                if (dir == null) {
                    continue;
                }

                for (LogProgress logProgress : progress.getProgressList()) {
                    LogTail logTail = new LogTail(dir, logProgress.getLogType(), logProgress.getStopLogDay(), logProgress.getStopLogLine());
                    logTailList.add(logTail);
                }
            }


            //启动日志线程
            countDownLatch = new CountDownLatch(1);
            stopCollect = false;

            Thread t = new Thread(new LogCollectThread(), "LogCollectThread");
            t.start();

        }
    }

    /**
     * 停止日志收集
     */
    public void stopLogCollect() {

        synchronized (this) {

            //关闭线程
            stopCollect = true;
            if( countDownLatch != null && countDownLatch.getCount() > 0 ) {
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    LOG.error(e);
                }
            }

            //关闭所有的日志Tail
            for (int i = 0; i < logTailList.size(); i++) {
                LogTail logTail = logTailList.get(i);
                logTail.close();
            }

            logTailList.clear();
        }

    }


    private LogDir getLogDir(ServerInfo serverInfo) {

        if (serverInfo == null) {
            return null;
        }

        for (int i = 0; i < logDirs.size(); i++) {
            LogDir dir = logDirs.get(i);
            if (dir.getGameId().equals(serverInfo.getGameId()) &&
                    dir.getAreaId().equals(serverInfo.getAreaId()) &&
                    dir.getServerId().equals(serverInfo.getServerId())) {
                return dir;
            }
        }

        return null;
    }



    private class LogCollectThread implements Runnable {

        public void run() {

            LOG.info("日志采集线程开始");

            while (true) {

                try {

                    if (stopCollect) {
                        LOG.debug("日志采集线程被中断");
                        break;
                    }


                    long startMils = System.currentTimeMillis();

                    //循环所有的Tail, 读取日志， 发送到服务器
                    for (int i = 0; i < logTailList.size(); i++) {
                        LogTail logTail = logTailList.get(i);

                        boolean isEnd = logTail.tail(startMils, tailProcessor, DEFAULT_TAIL_LINE_SIZE);
                    }

                    long sleepMils = (startMils + DEFAULT_A_LOOP_MILS - System.currentTimeMillis());
                    if (sleepMils > 0) {
                        Thread.sleep(sleepMils);
                    }

                } catch (InterruptedException e) {
                    LOG.error(e);
                } catch (IOException e) {
                    LOG.error(e);
                }
            }

            countDownLatch.countDown();
            LOG.info("日志采集线程结束");

        }

    }

}
